package com.demo.code;

import java.io.BufferedReader;
import java.io.File;
import java.io.FileReader;
import java.io.IOException;
import java.util.ArrayList;
import java.util.List;

/**
 * 统计java文件的代码行数 success 参考：CodeCount  http://t.csdnimg.cn/56le6
 */
public class GitlabCodeCount {

    public static void main(String[] args) throws IOException {
        // 项目路径
        String projectPath = "D:\\data\\test_template\\tool";
        // 用递归循环搜索某一个目录下的所有文件（文件和文件夹）
        List<String> fileList = new ArrayList<>();
        traverse(new File(projectPath), fileList);
        StatisticCodeLineVo result = codeLineCount(fileList);
        System.out.println("总代码行数：" + result.getTotalCodeLine() + "行");
        System.out.println("去掉空行、注释、导包行、包名行后的代码行数：" + result.getFilterTotalCodeLine() + "行");

    }

    /**
     * 用递归循环搜索某一个目录下的所有文件（文件和文件夹）
     *
     * @param dir
     * @param fileList 所有文件路径的集合
     */
    public static void traverse(File dir, List<String> fileList) {
        if (dir == null && !dir.exists() || dir.isFile()) {
            return;
        }
        // 读取出该目录下的所有文件
        File[] files = dir.listFiles();
        for (File file : files) {
            // 如果是文件，加入到文件集合中否则加入到文件夹集合中
            if (file.isFile()) {
                fileList.add(file.toString());
            }
            // 如果是文件夹，加入到文件夹集合中，并且再次调用traverse方法
            if (file.isDirectory()) {
                traverse(file, fileList);
            }
        }
    }

    /**
     * 统计代码行数
     *
     * @param fileList 文件列表
     * @return
     * @throws IOException
     */
    public static StatisticCodeLineVo codeLineCount(List<String> fileList) throws IOException {
        StatisticCodeLineVo statisticData = new StatisticCodeLineVo();
        for (String fileItem : fileList) {
            //统计指定类型的文件
            try {
                if (fileItem.endsWith(".java") || fileItem.endsWith(".yml") || fileItem.endsWith(".yaml") || fileItem.endsWith(".properties") || fileItem.endsWith(".xml") || fileItem.endsWith(".py") || fileItem.endsWith(".cpp") || fileItem.endsWith(".c") ||
                        fileItem.endsWith(".html") || fileItem.endsWith(".vue") || fileItem.endsWith(".js") || fileItem.endsWith(".css") || fileItem.endsWith(".go") || fileItem.endsWith(".ts") ||
                        fileItem.endsWith(".kt") || fileItem.endsWith(".swift") || fileItem.endsWith(".scss")) {
                    // 空行统计
                    int blankCount = 0;
                    // 单行注释
                    int commentCount = 0;
                    // 多行注释
                    int commentsCount = 0;
                    // 多行注释临时统计变量
                    int commentsTempCount = 0;
                    // 多行注释判断标志
                    boolean flag = false;
                    // 包名行
                    int packageCount = 0;
                    // 导包行
                    int importCount = 0;
                    // 当前行内容
                    String contentLine;
                    // 读取
                    BufferedReader br = new BufferedReader(new FileReader(fileItem));
                    // 定义行数，用于统计该文件内的代码行数
                    int totalLine = 0;
                    // 按行循环遍历
                    while ((contentLine = br.readLine()) != null) {
                        totalLine++;
                        // 空行
                        if ("".equals(contentLine.trim())) {
                            blankCount += 1;
                        }
                        // 单行注释
                        if (contentLine.trim().startsWith("//")) {
                            commentCount += 1;
                        }
                        // 多行注释标志
                        if (flag) {
                            commentsTempCount += 1;
                        }
                        // 多行注释判断
                        if (contentLine.trim().startsWith("/**")) {
                            commentsTempCount = 1;
                            flag = true;
                        }

                        // 多行注释结束判断
                        if (contentLine.trim().startsWith("*/")) {
                            commentsCount += commentsTempCount;
                            flag = false;
                            commentsTempCount = 0;
                        }
                        // 导包行
                        if (contentLine.trim().startsWith("import")) {
                            importCount += 1;
                        }
                        // 包名行
                        if (contentLine.trim().startsWith("package")) {
                            packageCount += 1;
                        }
                    }
                    // 关闭通道
                    br.close();
                    // 总代码行数为当前文件的行数累加
                    statisticData.setTotalCodeLine(statisticData.getTotalCodeLine() + totalLine);
                    statisticData.setFilterTotalCodeLine(statisticData.getFilterTotalCodeLine() + (totalLine - blankCount - commentCount - commentsCount - packageCount - importCount));
                }
            } catch (Exception e) {
                continue;
            }
        }
        return statisticData;
    }
}
